package com.yjt.zdjf.standard.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class AbstractStandarService<STD_REQ, STD_RSP, STD_DMN> {

	private final Logger logger = LoggerFactory.getLogger(AbstractStandarService.class);
	
	/**
	 * 请求报文转换成标准实体
	 * @param request
	 * @return
	 * @throws Exception
	 */
	public abstract STD_DMN msgConvertToDomain(STD_REQ request) throws Exception;
	
	/**
	 * 标准实体格式校验
	 * @param txnObject
	 * @return
	 * @throws Exception
	 */
	public abstract boolean checkFieldFormat(STD_DMN txnObject) throws Exception;
	
	/**
	 * 检查业务要素
	 * @param txnObject
	 * @return
	 * @throws Exception
	 */
	public abstract boolean checkBussinessElement(STD_DMN txnObject) throws Exception;
	
	/**
	 * 组装相关业务要素，默认空实现
	 * @param txnObject
	 * @return
	 * @throws Exception
	 */
	public void processBussinessElement(STD_DMN txnObject) throws Exception { };
	
	/**
	 * 持久化数据库
	 * @param txnObject
	 * @throws Exception
	 */
	public abstract void makePersistent(STD_DMN txnObject) throws Exception;
	
	/**
	 * 组装请求报文
	 * @param txnObject
	 * @return
	 * @throws Exception
	 */
	public abstract STD_REQ assembleReq(STD_DMN txnObject) throws Exception;
	
	/**
	 * 发送请求，并接收回应
	 * @param txnObject
	 * @return
	 * @throws Exception
	 */
	public abstract STD_RSP processRsp(STD_REQ request) throws Exception;
	
	
	/**
	 * 处理过程出现异常，并处理
	 * @param sourceObject 源请求报文实体
	 * @param cause 异常
	 * @return
	 */
	public abstract STD_RSP processError(STD_REQ request, Throwable cause);
	
	/**
	 * 处理请求入口
	 * @param request
	 * @return
	 */
	public STD_RSP processReq(STD_REQ request) {
		try {
			/*0.报文转换成实体*/
			STD_DMN txnObject = msgConvertToDomain(request);
			/*1.报文格式校验*/
			checkFieldFormat(txnObject);
			/*2.业务要素校验*/
			checkBussinessElement(txnObject);
			/*3.组装业务要素*/
			processBussinessElement(txnObject);
			/*4.入库*/
			makePersistent(txnObject);
			/*5.根据组装请求报文*/
			request = assembleReq(txnObject);
			/*6.根据不同的通讯方式，发送请求报文，并接收回应*/
			return processRsp(request);
		} catch(Exception e) {
			logger.error("[抽象服务层]发生错误，根据原始请求报文构造失败回应", e);
			return processError(request, e);
		}
	}
	
	
}
